package com.winhxd.b2c.order.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.winhxd.b2c.common.cache.Cache;
import com.winhxd.b2c.common.cache.Lock;
import com.winhxd.b2c.common.cache.RedisLock;
import com.winhxd.b2c.common.constant.BusinessCode;
import com.winhxd.b2c.common.constant.CacheName;
import com.winhxd.b2c.common.domain.PagedList;
import com.winhxd.b2c.common.domain.ResponseResult;
import com.winhxd.b2c.common.domain.customer.model.CustomerDeliveryInfo;
import com.winhxd.b2c.common.domain.order.condition.*;
import com.winhxd.b2c.common.domain.order.enums.*;
import com.winhxd.b2c.common.domain.order.model.*;
import com.winhxd.b2c.common.domain.order.vo.*;
import com.winhxd.b2c.common.domain.pay.condition.PayRefundCondition;
import com.winhxd.b2c.common.domain.pay.vo.PayRefundVO;
import com.winhxd.b2c.common.domain.product.condition.ProductStockSkuCondition;
import com.winhxd.b2c.common.exception.BusinessException;
import com.winhxd.b2c.common.feign.customer.DeliveryInfoServiceClient;
import com.winhxd.b2c.common.feign.pay.PayServiceClient;
import com.winhxd.b2c.common.feign.product.ProductServiceClient;
import com.winhxd.b2c.common.mq.MQDestination;
import com.winhxd.b2c.common.mq.StringMessageSender;
import com.winhxd.b2c.common.util.JsonUtil;
import com.winhxd.b2c.order.dao.*;
import com.winhxd.b2c.order.service.OrderAfterSaleDetailService;
import com.winhxd.b2c.order.service.OrderAfterSaleService;
import com.winhxd.b2c.order.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author:zhangyanwei
 * @date:2019/1/7 18:33:15
 * @Description:售后订单服务接口实现类
 **/
@Service
public class OrderAfterSaleServiceImpl implements OrderAfterSaleService {

	private static final Logger logger = LoggerFactory.getLogger(OrderAfterSaleServiceImpl.class);
	private static final Integer UPDATE_SUCCESS = 1;

	/**
	 * 退款成功
	 */
	private static final Integer REFUND_SUCCESS = 1;
	/**
	 * 退款失败
	 */
	private static final Integer REFUND_FAIL = 0;
	/**
	 * 退款中
	 */
	private static final Integer REFUND_PROCESS = 2;
	/**
	 * 待发货退款失败
	 */
	private static final Integer WAIT_DELIVER_REFUND_FAIL = 3;
	/**
	 * 售后类型：待发货退款
	 */
	private static final Integer WAIT_DELIVER_REFUND = 1;
	/**
	 * 售后类型：已发货退货退款
	 */
	private static final Integer DELIVERED_REFUND = 2;
	/**
	 * 售后类型：已发货换货
	 */
	private static final Integer DELIVERED_EXCHANGE = 3;
	/**
	 * 售后类型：已完成退货退款
	 */
	private static final Integer FINISHED_REFUND = 5;
	/**
	 * 售后类型：已完成换货
	 */
	private static final Integer FINISHED_EXCHANGE = 6;
	/**
	 * 退回至：1-微信
	 */
	private static final Integer REFUND_TO = 1;
	/**
	 * 退回方式：1-原路返回
	 */
	private static final Integer REFUND_TYPE = 1;
	private static final int AFTER_SALE_UPDATE_LOCK_EXPIRES_TIME = 2000;
	private static final int AFTER_SALE_REFUND_LOCK_EXPIRES_TIME = 3000;
	private static final int MAX_ORDER_POSTFIX = 99999;

	/**快递类型
	 * */
	private static final Integer ORDER_DICT_TYPE = 5;

	@Resource
	private OrderAfterSaleDetailService orderAfterSaleDetailService;

	@Autowired
	private OrderAfterSaleDetailMapper orderAfterSaleDetailMapper;

	@Autowired
	private OrderRefundInfoMapper orderRefundInfoMapper;

	@Autowired
	private OrderDetailMapper orderDetailMapper;

	@Autowired
	private OrderProductAttributeMapper orderProductAttributeMapper;

	@Autowired
	private OrderAfterSaleMapper orderAfterSaleMapper;

	@Autowired
	private OrderInfoMapper orderInfoMapper;

	@Autowired
	private OrderExpressInfoMapper orderExpressInfoMapper;

	@Autowired
	private OrderPaymentMapper orderPaymentMapper;

	@Autowired
	private PayServiceClient payServiceClient;

	@Autowired
	private OrderCancelInfoMapper orderCancelInfoMapper;

	@Autowired
	private OrderLogMapper orderLogMapper;

	@Autowired
	private StringMessageSender stringMessageSender;

	@Autowired
	private DeliveryInfoServiceClient deliveryInfoServiceClient;

	@Autowired
	private OrderDictInfoMapper orderDictInfoMapper;

	@Autowired
	private Cache cache;

	@Autowired
	private ProductServiceClient productServiceClient;



	@Override
	public OrderAfterSaleVO getCheckOrderAfterSale(OrderAfterSaleCondition condition) {
		if(StringUtils.isEmpty(condition.getOrderNo())){
			throw new BusinessException(BusinessCode.CODE_461804);
		}
		OrderAfterSaleVO saleVO = new OrderAfterSaleVO();
		// 获取订单明细表
		List<OrderDetailVO> orderDetail = this.getOrderDetailByCondition(condition);
		// 查询售后订单信息
		OrderInfoVO orderInfo = this.getOrderInfoByCondition(condition);
		if(Objects.isNull(orderInfo)){
			throw new BusinessException(BusinessCode.ORDER_DOES_NOT_EXIST);
		}
		orderInfo.setOrderDetailVOList(orderDetail);

		// 获取订单售后申请详细表
		List<OrderAfterSaleDetailVO> saleDetail = this.getOrderAfterSaleDetailByCondition(condition);

		//组装数据
		OrderAfterSaleInfoVO orderAfterSaleInfoVO = new OrderAfterSaleInfoVO();
		orderAfterSaleInfoVO.setOrderAfterSaleDetail(saleDetail);

		// 查询订单取消原因
		List<OrderCancelInfoVO> orderCancelInfoVO = new ArrayList<>();
		if(!CollectionUtils.isEmpty(saleDetail)){
			for(OrderAfterSaleDetailVO detail:saleDetail){
				if(Objects.nonNull(detail)){
					condition.setAfterSaleDetailId(detail.getId());
					orderCancelInfoVO = this.getOrderCancelInfoVOByCondition(condition);
					orderAfterSaleInfoVO.setOrderCancelInfoVO(orderCancelInfoVO);
				}
			}
		}

		// 查询售后物流信息
		List<OrderExpressInfoVO> orderExpressInfo = this.getOrderExpressInfoByCondition(condition);

		// 查询售后退款信息
		List<OrderRefundInfoVO> orderRefundInfo = this.getOrderRefundInfoByCondition(condition);

		// 查询送货方式和快递公司信息下拉选项
		OrderAfterSaleChangeInfo changeInfo = this.getOrderAfterSaleChangeInfo();

		saleVO.setOrderAfterSaleInfoVO(orderAfterSaleInfoVO);
		saleVO.setOrderExpressInfo(orderExpressInfo);
		saleVO.setOrderInfo(orderInfo);
		saleVO.setOrderRefundInfo(orderRefundInfo);
		saleVO.setOrderAfterSaleChangeInfo(changeInfo);
		return saleVO;
	}


	@Override
	public PagedList<OrderAfterSaleDetailVO> findOrderAfterSaleDetailList(OrderAfterSaleListCondition condition) {
		PagedList<OrderAfterSaleDetailVO> pagedList = new PagedList<>();
		PageHelper.startPage(condition.getPageNo(),condition.getPageSize());
		List<OrderAfterSaleDetailVO> saleDetail = this.findOrderAfterSaleDetailInfoList(condition);
		PageInfo<OrderAfterSaleDetailVO> pageInfo = new PageInfo<>(saleDetail);
		pagedList.setData(pageInfo.getList());
		pagedList.setPageNo(pageInfo.getPageNum());
		pagedList.setPageSize(pageInfo.getPageSize());
		pagedList.setTotalRows(pageInfo.getTotal());
		return pagedList;
	}

	@Override
	public List<OrderAfterSaleDetailVO> findOrderAfterSaleDetailInfoList(OrderAfterSaleListCondition condition) {
		if(condition.getSaleType() != null && condition.getSaleType() != 0){
			logger.info("售后列表查询条件退/换货选择类型："+condition.getSaleType());
			List<Integer> afterSaleType = getAfterSaleTypeForPage(condition.getSaleType());
			condition.setSaleTypeTmp(afterSaleType);
			logger.info("售后列表查询条件退/换货 选中后转换的售后类型："+afterSaleType.toString());
		}
		// 获取订单售后申请详细表
		List<OrderAfterSaleDetailVO> saleDetail = this.getOrderAfterSaleDetailListByCondition(condition);
		return saleDetail;
	}

	@Override
	public OrderAfterSaleChangeInfo getOrderAfterSaleChangeInfo() {
		OrderAfterSaleChangeInfo changeInfo = new OrderAfterSaleChangeInfo();
		ResponseResult<List<CustomerDeliveryInfo>> deliveryInfo = deliveryInfoServiceClient.findDeliveryInfo();
		List<CustomerDeliveryInfo> deliveryInfoData = deliveryInfo.getData();
		changeInfo.setCustomerDeliveryInfo(deliveryInfoData);
		//获取快递方式
		OrderDictInfo dictInfo = new OrderDictInfo();
		dictInfo.setType(ORDER_DICT_TYPE);
		List<OrderDictInfoVO> dictInfoList = orderDictInfoMapper.selectListByModel(dictInfo);
		changeInfo.setOrderDictInfoVO(dictInfoList);
		return changeInfo;
	}
	/**
	 * @author zhanghuan
	 * @date  2018年10月26日 下午2:11:57
	 * @Description 根据售后列表页面传递的退货换货仅退款返回售后类型
	 * @param saleType 退货/换货/仅退款
	 * ONLY_RETURN_MONEY( 1, "仅退款"),
	 * RETURN_GOODS( 2, "退货"),
	 * CHANGE_GOODS( 3, "换货");
	 */
	private List<Integer> getAfterSaleTypeForPage(int saleType){
		List<Integer> afterSalType = new ArrayList<>();
		if(AfterSaleReturnStatusEnum.ONLY_RETURN_MONEY.getTypeCode().intValue() == saleType){
			afterSalType.add(OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode());
		}else if(AfterSaleReturnStatusEnum.RETURN_GOODS.getTypeCode().intValue() == saleType){
			afterSalType.add(OrderAfterSaleTypeEnum.WAIT_RECEIVING_REFUND_AND_RETURN.getTypeCode());
			afterSalType.add(OrderAfterSaleTypeEnum.FINISHED_REFUND_AND_RETURN.getTypeCode());
		}else if(AfterSaleReturnStatusEnum.CHANGE_GOODS.getTypeCode().intValue() == saleType){
			afterSalType.add(OrderAfterSaleTypeEnum.WAIT_RECEIVING_EXCHANGE.getTypeCode());
			afterSalType.add(OrderAfterSaleTypeEnum.FINISHED_EXCHANGE.getTypeCode());
		}
		return afterSalType;
	}


	/**
	 * @author zhanghuan
	 * @date  2018年10月26日 下午2:11:57
	 * @Description 根据售后类型 返回售后列表中 退货/换货 仅退款 的描述
	 * @param afterSaleType 售后类型
	 */
	private String getSaleReturnDec(int afterSaleType){
		String returndec = "";
		// 仅退款
		if(OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode().intValue() == afterSaleType){
			returndec = AfterSaleReturnStatusEnum.ONLY_RETURN_MONEY.getTypeDesc();
			return returndec;
			// 退货
		}else if(OrderAfterSaleTypeEnum.WAIT_RECEIVING_REFUND_AND_RETURN.getTypeCode().intValue() == afterSaleType
			|| OrderAfterSaleTypeEnum.FINISHED_REFUND_AND_RETURN.getTypeCode().intValue() == afterSaleType){
			returndec = AfterSaleReturnStatusEnum.RETURN_GOODS.getTypeDesc();
			return returndec;
			// 换货
		}else if(OrderAfterSaleTypeEnum.WAIT_RECEIVING_EXCHANGE.getTypeCode().intValue() == afterSaleType
				|| OrderAfterSaleTypeEnum.FINISHED_EXCHANGE.getTypeCode().intValue() == afterSaleType){
			returndec = AfterSaleReturnStatusEnum.CHANGE_GOODS.getTypeDesc();
			return returndec;
		}
		return returndec;
	}

	@Override
	public List<OrderAfterSaleDetailVO> getOrderAfterSaleDetailListByCondition(OrderAfterSaleListCondition condition) {
		List<OrderAfterSaleDetailVO> saleDetail = orderAfterSaleDetailMapper.selectOrderAfterSaleDetailListByCondition(condition);
		if(!CollectionUtils.isEmpty(saleDetail)){
			for(OrderAfterSaleDetailVO detail:saleDetail){
				if(Objects.nonNull(detail)){
					OrderAfterSaleCondition con = new OrderAfterSaleCondition();
					con.setOrderNo(condition.getOrderNo());
					String saleStatus = AfterSaleViewStatusEnum.getAfterSaleViewStatusEnumByCode(detail.getViewStatus()).getTypeDesc();
					detail.setResultStatusName(saleStatus);
					String returnDec = this.getSaleReturnDec(detail.getAfterSaleType());
					if(!StringUtils.isEmpty(returnDec)){
						detail.setSaleReturnDec(returnDec);
					}else{
						throw new BusinessException(BusinessCode.CODE_1001);
					}
					boolean showStatus = getSaleCloseBtnShowStatus(detail);
					detail.setBtnshow(showStatus);
				}
			}
		}
		return saleDetail;
	}

	/**
	 * @author zhanghuan
	 * @date  2018年10月26日 下午2:11:57
	 * @Description 返回页面 关闭售后 按钮的展示或隐藏状态
	 */
	private boolean getSaleCloseBtnShowStatus(OrderAfterSaleDetailVO detail){
		boolean status = true;
		// 根据订单号获取订单主表信息
		OrderInfo orderInfo = orderInfoMapper.selectByOrderNo(detail.getOrderNo());
		if(Objects.isNull(orderInfo)){
			throw new BusinessException(BusinessCode.ORDER_DOES_NOT_EXIST);
		}
		// 如果当前的订单状态是6-已完成7-已关闭 则列表的 关闭售后 按钮不展示
		if(OrderStatusEnum.FINISHED.getStatusCode() == orderInfo.getStatus().intValue() || OrderStatusEnum.CLOSE.getStatusCode() == orderInfo.getStatus().intValue()){
			logger.info("当前售后订单的订单状态{}"+OrderStatusEnum.FINISHED.getStatusCode()+"-"+OrderStatusEnum.FINISHED.getStatusDes());
			status = false;
			return status;
		}
		// 如果当前的售后完成状态为已完成 则列表的 关闭售后 按钮不展示
		if(CommonStatusEnum.YES.getTypeCode().intValue() == detail.getCompleteStatus().intValue()){
			status = false;
			return status;
		}

		// 如果当前状态是 仅退款已审核 状态 则 关闭售后按钮不显示
		if(OrderAfterSaleTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode().intValue() == detail.getAfterSaleType()
				&& AfterSaleViewStatusEnum.CHECKED.getTypeCode().intValue() == detail.getViewStatus().intValue()){
			status = false;
			return status;
		}

		if(AfterSaleViewStatusEnum.REFUSE.getTypeCode().intValue() == detail.getViewStatus().intValue()
		||AfterSaleViewStatusEnum.REFUNDED.getTypeCode().intValue() == detail.getViewStatus().intValue()
		||AfterSaleViewStatusEnum.EXCHANGED.getTypeCode().intValue() == detail.getViewStatus().intValue()
		||AfterSaleViewStatusEnum.CANCLED.getTypeCode().intValue() == detail.getViewStatus().intValue()
		||AfterSaleViewStatusEnum.CLOSED.getTypeCode().intValue() == detail.getViewStatus().intValue()
		||AfterSaleViewStatusEnum.REFUNDING.getTypeCode().intValue() == detail.getViewStatus().intValue()
		||AfterSaleViewStatusEnum.HANDLE_CLOSED.getTypeCode().intValue() == detail.getViewStatus().intValue()){
			status = false;
			return status;
		}
		return status;
	}

	@Override
	public List<OrderCancelInfoVO> getOrderCancelInfoVOByCondition(OrderAfterSaleCondition condition) {
		return orderCancelInfoMapper.selectOrderCancelInfoVOByCondition(condition);
	}

	@Override
	public List<OrderDetailVO> getOrderDetailByCondition(OrderAfterSaleCondition condition) {
		List<OrderDetailVO> orderDetailVOS = orderDetailMapper.selectOrderDetailByCondition(condition);
		//商品总价
		BigDecimal totalMoney = orderDetailVOS.stream().map(OrderDetailVO::getSubTotal).reduce(BigDecimal.ZERO, BigDecimal::add);
		if(!CollectionUtils.isEmpty(orderDetailVOS)){
			for(OrderDetailVO vo:orderDetailVOS){
				vo.setTotalMoney(totalMoney);
				if(Objects.nonNull(vo)){
					// 根据订单明细id获取 商品属性id；根据商品属性id获取 商品对应的尺码颜色
					List<OrderProductAttribute> attr = orderProductAttributeMapper.selectAttributeByProduId(vo.getId());
					vo.setAttributes(attr);
				}
			}
		}
		return orderDetailVOS;
	}

	@Override
	public List<OrderAfterSaleDetailVO> getOrderAfterSaleDetailByCondition(OrderAfterSaleCondition condition) {
		List<OrderAfterSaleDetailVO> saleDetail = orderAfterSaleDetailMapper.selectOrderAfterSaleDetailByCondition(condition);
		if(!CollectionUtils.isEmpty(saleDetail)){
			for(OrderAfterSaleDetailVO detail:saleDetail){
				if(Objects.nonNull(detail)){
					OrderAfterSaleCondition con = new OrderAfterSaleCondition();
					con.setOrderNo(condition.getOrderNo());
					String saleStatus = AfterSaleViewStatusEnum.getAfterSaleViewStatusEnumByCode(detail.getViewStatus()).getTypeDesc();
					detail.setResultStatusName(saleStatus);
					String returnDec = this.getSaleReturnDec(detail.getAfterSaleType());
					if(!StringUtils.isEmpty(returnDec)){
						detail.setSaleReturnDec(returnDec);
					}else{
						throw new BusinessException(BusinessCode.CODE_1001);
					}
				}
			}
		}
		return saleDetail;
	}

	@Override
	public OrderAfterSale getOrderAfterSaleByCondition(OrderAfterSaleCondition condition) {
		return orderAfterSaleMapper.selectOrderAfterSaleByCondition(condition);
	}

	@Override
	public OrderInfoVO getOrderInfoByCondition(OrderAfterSaleCondition condition) {
		return orderInfoMapper.selectOrderInfoByCondition(condition);
	}

	@Override
	public List<OrderExpressInfoVO> getOrderExpressInfoByCondition(OrderAfterSaleCondition condition) {
		return orderExpressInfoMapper.selectOrderExpressInfoByCondition(condition);
	}

	@Override
	public List<OrderRefundInfoVO> getOrderRefundInfoByCondition(OrderAfterSaleCondition condition) {
		return orderRefundInfoMapper.selectOrderRefundInfoByCondition(condition);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Integer modifyAfterSaleOrderByStatus(OrderAfterSaleCheckCondition condition) {
		String log="审核修改售后详细信息OrderAfterSaleServiceImpl--";
		logger.info(log + "修改售后详细信息开始");
		String lockKey = CacheName.CACHE_KEY_MODIFY_AFTER_SALE+condition.getOrderNo();
		if(null != condition.getSkuId()) {
			lockKey+=condition.getSkuId();
		}
		Lock lock = new RedisLock(cache, lockKey, AFTER_SALE_UPDATE_LOCK_EXPIRES_TIME);
		if (lock.tryLock()) {
			try {
				//保存日志
				OrderLog orderLog = new OrderLog();
				this.buildOrderLogByCheck(condition,orderLog);
				this.saveOrderLog(orderLog);
				//校验该售后是否被手动关闭
				orderAfterSaleDetailService.validateCloseAfterSaleStatus(condition.getId());
				//获得售后详细信息
				OrderAfterSaleDetail detail = orderAfterSaleDetailMapper.selectByPrimaryKey(condition.getId());
				if(null == detail){
					throw new BusinessException(BusinessCode.CODE_460023);
				}
				//校验审核时，用户是否取消售后
				if(detail.getResultStatus().intValue() == AfterSaleAuditStatusEnum.CANCEL.getTypeCode().intValue()){
					throw new BusinessException(BusinessCode.CODE_460008);
				}
				//获得审核结果
				Boolean checkRes = (detail.getViewStatus().intValue() == AfterSaleViewStatusEnum.CHECKED.getTypeCode().intValue() ||
						detail.getViewStatus().intValue() == AfterSaleViewStatusEnum.REFUSE.getTypeCode().intValue());
				//校验审核时，是否已审核
				if(checkRes){
					throw new BusinessException(BusinessCode.CODE_460013);
				}
				//售后类型为待发货仅退款时并且审核结果同意->调用操作库存方法和退款方法
				if((AfterSaleAuditStatusEnum.YES.getTypeCode()).intValue()==condition.getResultStatus().intValue()){
					if(condition.getAfterSaleType().intValue()==WAIT_DELIVER_REFUND.intValue()){
						//调用操作库存方法
						List<ProductStockSkuCondition> list = this.buildProductStockSku(condition);
						productServiceClient.operateAddProductStock(list).getDataWithException();
						//调用退款方法
						Integer refundRes = this.invokeSaveRefund(condition);
						if(refundRes < REFUND_SUCCESS){
							logger.info(log + "售后待发货仅退款：审核同意退款失败");
							return REFUND_FAIL;
						}
					}
				}
				OrderAfterSaleDetail orderAfterSaleDetail = new OrderAfterSaleDetail();
				this.buildOrderAfterSale(condition, orderAfterSaleDetail);
				//更新售后详细信息
				orderAfterSaleDetailMapper.updateByPrimaryKeySelective(orderAfterSaleDetail);
			} finally {
				lock.unlock();
			}
		}else {
			throw new BusinessException(BusinessCode.CODE_440603);
		}
		//所有审核拒绝时，调用修改订单方法
		if(condition.getResultStatus().intValue() == AfterSaleAuditStatusEnum.NO.getTypeCode().intValue()){
			logger.info(log + "售后审核调用修改订单方法开始");
			orderAfterSaleDetailService.updateOrderStatus(condition.getOrderNo());
		}else{
			//审核同意时，且售后类型是2-已发货退货退款、3-已发货换货、 5-已完成退货退款、6、已完成换货  发送延时队列
			if(condition.getAfterSaleType().intValue() == DELIVERED_REFUND.intValue() ||
					condition.getAfterSaleType().intValue()== DELIVERED_EXCHANGE.intValue() ||
					condition.getAfterSaleType().intValue() == FINISHED_REFUND.intValue() ||
					condition.getAfterSaleType().intValue() == FINISHED_EXCHANGE.intValue()){
				logger.info(log + "售后退换货发送延时队列 开始");
				Integer autoExchangeDay = 0;
				OrderInfo orderInfo = orderInfoMapper.selectByOrderNo(condition.getOrderNo());
				if(null != orderInfo && null != orderInfo.getAutoExchangeDay()){
					autoExchangeDay = orderInfo.getAutoExchangeDay().intValue();
				}
				stringMessageSender.send(MQDestination.OUTLET_ORDER_RETURNING_TIMEOUT_DELAYED, String.valueOf(condition.getId()), autoExchangeDay * 24 * 60 * 60 * 1000);
			}
		}
		return UPDATE_SUCCESS;
	}

	/**
	 * 构造加库存入参
	 * @param condition
	 * @return
	 */
	private List buildProductStockSku(OrderAfterSaleCheckCondition condition){
		logger.info("售后待发货仅退款：构造库存入参-{}", JsonUtil.toJSONString(condition));
		List<ProductStockSkuCondition> list = new ArrayList<>();
		List<OrderDetailVO> voList = orderDetailMapper.selectListByOrderNo(condition.getOrderNo());
		if(null != voList){
			for(OrderDetailVO vo: voList){
				ProductStockSkuCondition con = new ProductStockSkuCondition();
				con.setSkuId(vo.getSkuId());
				con.setSkuNum(Long.valueOf(vo.getNumber())*-1);
				list.add(con);
			}
		}else{
			throw new BusinessException(BusinessCode.CODE_406101);
		}
		logger.info("售后待发货仅退款：构造库存返参-{}", JsonUtil.toJSONString(list));
		return list;
	}

	/**
	 * 调用退款接口
	 * @param condition
	 */
	private Integer invokeSaveRefund(OrderAfterSaleCheckCondition condition){
		//售后类型：待发货退款。且审核同意，调用退款接口
		logger.info("售后待发货退款调用退款接口开始");
		OrderAfterSaleRefundCondition refundCondition = new OrderAfterSaleRefundCondition();
		this.buildAfterSaleRefundByCheck(condition, refundCondition);
		this.buildOrderRefundInfo(refundCondition);
		return this.saveRefundInfo(refundCondition);
	}

	/**
	 * 构造售后明细
	 * @param condition
	 * @param orderAfterSaleDetail
	 * @return
	 */
	private void buildOrderAfterSale(OrderAfterSaleCheckCondition condition, OrderAfterSaleDetail orderAfterSaleDetail){
		Date now = new Date();
		orderAfterSaleDetail.setId(condition.getId());
		orderAfterSaleDetail.setAfterSaleType(condition.getAfterSaleType());
		orderAfterSaleDetail.setResultStatus(condition.getResultStatus());
		orderAfterSaleDetail.setResultDesc(condition.getResultDesc());
		orderAfterSaleDetail.setResultTime(now);
		//售后状态当会员仅在退换货中，填写快递单号过程中超过设置时间时，此状态才设置为 关闭。
		orderAfterSaleDetail.setAfterSaleStatus(AfterSaleStatusEnum.NORMAL.getTypeCode());
		//审核拒绝时，售后完成状态为已完成
		if((AfterSaleAuditStatusEnum.NO.getTypeCode()).intValue()==condition.getResultStatus().intValue()){
			orderAfterSaleDetail.setCompleteStatus(AfterSaleCompleteStatusEnum.COMPLETED.getTypeCode());
			orderAfterSaleDetail.setViewStatus(AfterSaleViewStatusEnum.REFUSE.getTypeCode());
			orderAfterSaleDetail.setCompleteTime(now);
		//审核通过时，页面状态改为已审核
		}else {
			orderAfterSaleDetail.setViewStatus(AfterSaleViewStatusEnum.CHECKED.getTypeCode());
		}
		orderAfterSaleDetail.setUpdated(now);
		orderAfterSaleDetail.setResultUser(condition.getResultUser());
		orderAfterSaleDetail.setUpdatedBy(condition.getResultUser());
	}

	/**
	 * 待发货退款-审核通过-构造退款入参
	 * @param condition
	 * @param refundCondition
	 */
	private void buildAfterSaleRefundByCheck(OrderAfterSaleCheckCondition condition, OrderAfterSaleRefundCondition refundCondition){
		refundCondition.setOrderNo(condition.getOrderNo());
		refundCondition.setSkuId(condition.getSkuId());
		refundCondition.setType(WAIT_DELIVER_REFUND);
		refundCondition.setAfterSaleDetailID(condition.getId());
		refundCondition.setCreatedBy(condition.getResultUser());
		refundCondition.setCreatedByName(condition.getResultUserName());
	}

	/**
	 * 构造审核日志明细
	 * @param condition
	 * @param orderLog
	 */
	private void buildOrderLogByCheck(OrderAfterSaleCheckCondition condition, OrderLog orderLog){
		String operationPropertity;
		orderLog.setOrderNo(condition.getOrderNo());
		orderLog.setSkuId(condition.getSkuId());
		orderLog.setCreated(new Date());
		operationPropertity = this.getOperationPropertityByCheck(condition.getResultStatus(),condition.getAfterSaleType());
		orderLog.setOperationProperty(operationPropertity);
	}

	/**
	 * 构造退款日志明细
	 * @param condition
	 * @param orderLog
	 */
	private void buildOrderLogByRefund(OrderAfterSaleRefundCondition condition, OrderLog orderLog){
		String operationPropertity;
		orderLog.setOrderNo(condition.getOrderNo());
		orderLog.setSkuId(condition.getSkuId());
		orderLog.setCreated(new Date());
		operationPropertity = this.getOperationPropertityByRefund(condition.getType());
		orderLog.setOperationProperty(operationPropertity);
	}

	/**
	 * 审核时获取操作记录类型(保存日志用)
	 * @param checkResult
	 * @param afterSaleType
	 * @return
	 */
	private String getOperationPropertityByCheck(Integer checkResult, Integer afterSaleType){
		//审核通过，根据售后类型得到相应信息
		if(AfterSaleAuditStatusEnum.YES.getTypeCode().intValue() == checkResult.intValue()){
			switch (afterSaleType){
				case 1:
					return OrderOperationPropertyEnum.AFTER_SALE_WAIT_DELIVERING_REFUND_AGREED.getPropertyDes();
				case 2:
					return OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_REFUND_AGREED.getPropertyDes();
				case 3:
					return OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_EXCHANGE_AGREED.getPropertyDes();
				case 5:
					return OrderOperationPropertyEnum.AFTER_SALE_FINISHED_REFUND_AGREED.getPropertyDes();
				case 6:
					return OrderOperationPropertyEnum.AFTER_SALE_FINISHED_EXCHANGE_AGREED.getPropertyDes();
				default:
					return null;
			}
		//审核拒绝，根据售后类型得到相应信息
		}else {
			switch (afterSaleType) {
				case 1:
					return OrderOperationPropertyEnum.AFTER_SALE_WAIT_DELIVERING_REFUND_REFUSE.getPropertyDes();
				case 2:
					return OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_REFUND_REFUSE.getPropertyDes();
				case 3:
					return OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_EXCHANGE_REFUSE.getPropertyDes();
				case 5:
					return OrderOperationPropertyEnum.AFTER_SALE_FINISHED_REFUND_REFUSE.getPropertyDes();
				case 6:
					return OrderOperationPropertyEnum.AFTER_SALE_FINISHED_EXCHANGE_REFUSE.getPropertyDes();
				default:
					return null;
			}
		}
	}

	/**
	 * 获取售后退款操作类型
	 * @param refundType
	 * @return
	 */
	private String getOperationPropertityByRefund(Integer refundType){
		switch (refundType){
			case 1:
				return OrderOperationPropertyEnum.AFTER_SALE_WAIT_DELIVERING_REFUND_PROCESS.getPropertyDes();
			case 2:
				return OrderOperationPropertyEnum.AFTER_SALE_WAIT_RECEIVING_REFUND_PROCESS.getPropertyDes();
			case 4:
				return OrderOperationPropertyEnum.AFTER_SALE_FINISHED_REFUND_PROCESS.getPropertyDes();
			default:
				return "";
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Integer saveRefundInfo(OrderAfterSaleRefundCondition condition) {
		//售后退款加锁
		String lockKey = CacheName.CACHE_KEY_REFUND_AFTER_SALE+condition.getOrderNo();
		if(null != condition.getSkuId()) {
			lockKey+=condition.getSkuId();
		}
		Lock lock = new RedisLock(cache, lockKey, AFTER_SALE_REFUND_LOCK_EXPIRES_TIME);
		if (lock.tryLock()) {
			try {
				String log="售后退款OrderAfterSaleServiceImpl--";
				logger.info(log + "售后保存退款信息接口开始");
				OrderRefundInfo orderRefundInfo;
				//保存日志，不影响主流程
				OrderLog orderLog = new OrderLog();
				try{
					this.buildOrderLogByRefund(condition, orderLog);
					this.saveOrderLog(orderLog);
				}catch (Exception e){
					logger.error("保存售后日志失败 日志实体：{}", JsonUtil.toJSONString(orderLog));
				}
				//验证该售后是否被手动关闭
				orderAfterSaleDetailService.validateCloseAfterSaleStatus(condition.getAfterSaleDetailID());
				//查询退款信息是否存在
				OrderRefundInfo refundInfo = this.getOrderRefundInfo(condition);
				logger.info("退款信息实体:{}", JsonUtil.toJSONString(refundInfo));
				//退款中 不能发起二次退款
				if(null != refundInfo && null != refundInfo.getRefundStatus() && refundInfo.getRefundStatus().intValue() == REFUND_PROCESS.intValue()){
					throw new BusinessException(BusinessCode.CODE_440606);
				}
				//退款成功 不能发起二次退款
				if(null != refundInfo && null != refundInfo.getRefundStatus() && refundInfo.getRefundStatus().intValue()==REFUND_SUCCESS.intValue()){
					throw new BusinessException(BusinessCode.CODE_460007);
				}
				//查询退款信息是否存在，存在使用原先退款流水号；否则新生成
				if(null != refundInfo){
					//构造支付退款接口入参
					this.buildRefundCondition(condition);
					condition.setRefundNo(refundInfo.getRefundNo());
				}else {
					//构造支付退款接口入参+保存退款信息
					orderRefundInfo = this.buildOrderRefundInfo(condition);
					this.verifyParams(condition);
					orderRefundInfoMapper.insertSelective(orderRefundInfo);
				}
				//获取支付退款结果
				Boolean payRes = this.getPayRefundResult(condition);
				if(!payRes){
					logger.error("调用支付退款接口失败");
					return REFUND_FAIL;
				}
			} finally {
				lock.unlock();
			}
			return UPDATE_SUCCESS;
		}else {
			throw new BusinessException(BusinessCode.CODE_440606);
		}
	}

	@Deprecated
	@Override
	public OrderExpressInfoVO getOrderExpressInfoForConsumer(OrderAfterSaleCondition condition) {
		return orderExpressInfoMapper.selectOrderExpressInfoForConsumer(condition);
	}

	/**
	 * 校验退款入参参数
	 * @param condition
	 */
	public void verifyParams(OrderAfterSaleRefundCondition condition){
		//查询订单信息
		OrderInfo orderInfo = orderInfoMapper.selectByOrderNo(condition.getOrderNo());
		if(null == orderInfo){
			throw new BusinessException(BusinessCode.ORDER_DOES_NOT_EXIST);
		}
		OrderAfterSaleDetail orderAfterSaleDetail = orderAfterSaleDetailMapper.selectByPrimaryKey(condition.getAfterSaleDetailID());
		if(null == orderAfterSaleDetail){
			throw new BusinessException(BusinessCode.CODE_460017);
		}
		if(null == condition.getTotalAmount()){
			throw new BusinessException(BusinessCode.WRONG_ORDER_TOTAL_MONEY);
		}
		if(null == condition.getRefundAmount()){
			throw new BusinessException(BusinessCode.CODE_460018);
		}
	}

	/**
	 * 获取支付退款结果
	 * @param condition
	 * @return
	 */
	private Boolean getPayRefundResult(OrderAfterSaleRefundCondition condition){
		logger.info("调用支付退款接口开始");
		PayRefundCondition payRefundCondition = new PayRefundCondition();
		this.buildPayRefundParams(condition, payRefundCondition);
		PayRefundVO  payRefundVO;
		try{
			ResponseResult<PayRefundVO> result = payServiceClient.orderRefund(payRefundCondition);
			payRefundVO = result.getDataWithException();
			logger.info("支付退款返参:{}",JsonUtil.toJSONString(payRefundVO));
			if(null !=payRefundVO && null != payRefundVO.getStatus()){
				//退款接收状态; 0:退款中,1:退款成功,2:退款关闭,3:退款异常
				String status = payRefundVO.getStatus();
				String refundProcess = "0";
				String refundSuccess = "1";
				if(refundProcess.equals(status) || refundSuccess.equals(status)){
					//成功调用支付退款接口后,修改售后状态为退款中
					this.modifyAfterSaleDetail(condition);
					//修改退款信息状态为：处理中
					this.modifyRefundInfoStatus(condition);
					return true;
				}else{
					return false;
				}
			}
			logger.info("调用支付退款接口结束：返参 {}", JsonUtil.toJSONString(payRefundVO));
		}catch (BusinessException be){
			logger.info("调用支付退款接口：业务异常{}",be);
			return false;
		}catch (Exception e){
			logger.info("调用支付退款接口：异常{}",e);
			return false;
		}
		return true;
	}



	/**
	 * 根据订单号和SKU获取退款信息
	 * @return
	 */
	private OrderRefundInfo getOrderRefundInfo(OrderAfterSaleRefundCondition condition){
		OrderRefundInfoCondition refundInfoCondition = new OrderRefundInfoCondition();
		this.buildOrderRefundInfoCondition(condition,refundInfoCondition);
		return orderRefundInfoMapper.selectRefundInfoByCondition(refundInfoCondition);
	}

	/**
	 * 构造查询退款信息返参
	 * @param refundCondition
	 * @param condition
	 */
	private void buildOrderRefundInfoCondition(OrderAfterSaleRefundCondition refundCondition, OrderRefundInfoCondition condition){
		condition.setOrderNo(refundCondition.getOrderNo());
		condition.setSku(refundCondition.getSkuId());
	}

	/**
	 * 修改售后详细表状态
	 * @param condition
	 * @return
	 */
	private void modifyAfterSaleDetail(OrderAfterSaleRefundCondition condition){
		Date now = new Date();
		OrderAfterSaleDetail orderAfterSaleDetail = orderAfterSaleDetailMapper.selectByPrimaryKey(condition.getAfterSaleDetailID());
		orderAfterSaleDetail.setViewStatus(AfterSaleViewStatusEnum.REFUNDING.getTypeCode());
		orderAfterSaleDetail.setUpdatedBy(String.valueOf(condition.getCreatedBy()));
		orderAfterSaleDetail.setUpdated(now);
		orderAfterSaleDetailMapper.updateByPrimaryKeySelective(orderAfterSaleDetail);
	}

	/**
	 * 修改退款状态
	 * @param condition
	 */
	private void modifyRefundInfoStatus(OrderAfterSaleRefundCondition condition){
		OrderRefundInfo info = orderRefundInfoMapper.selectRefundInfoByRefundNO(condition.getRefundNo());
		info.setRefundStatus(AfterSaleRefundStatusEnum.PROCESSING.getTypeCode());
		info.setUpdated(new Date());
		info.setUpdatedBy(String.valueOf(condition.getCreatedBy()));
		orderRefundInfoMapper.updateByPrimaryKeySelective(info);
	}

	/**
	 * 获得退款信息
	 * @param condition
	 * @return OrderRefundInfo
	 */
	private OrderRefundInfo buildOrderRefundInfo(OrderAfterSaleRefundCondition condition){
		this.buildRefundCondition(condition);
		OrderRefundInfo orderRefundInfo = new OrderRefundInfo();
		this.buildPayRefundParams(orderRefundInfo,condition);
		return orderRefundInfo;
	}

	/**
	 * 构造退款信息
	 */
	private void buildPayRefundParams(OrderRefundInfo refundInfo, OrderAfterSaleRefundCondition condition){
		OrderAfterSaleDetail detail = orderAfterSaleDetailMapper.selectByPrimaryKey(condition.getAfterSaleDetailID());
		Date now = new Date();
		refundInfo.setAfterSaleDetailId(condition.getAfterSaleDetailID());
		refundInfo.setOrderNo(condition.getOrderNo());
		refundInfo.setSkuId(condition.getSkuId());
		refundInfo.setType(condition.getType());
		refundInfo.setRefundNo(condition.getRefundNo());
		refundInfo.setRefundPrice(condition.getRefundAmount());
		refundInfo.setRefundType(REFUND_TYPE);
		refundInfo.setRefundTo(REFUND_TO);
		refundInfo.setRefundUser(String.valueOf(condition.getCreatedBy()));
		refundInfo.setCreatedBy(String.valueOf(condition.getCreatedBy()));
		refundInfo.setUpdatedBy(String.valueOf(condition.getCreatedBy()));
		refundInfo.setReceiveUser(detail.getApplyUser());
		refundInfo.setCreated(now);
		refundInfo.setUpdated(now);
	}

	/**
	 * 构造调用支付退款入参
	 */
	private void buildPayRefundParams(OrderAfterSaleRefundCondition condition, PayRefundCondition payRefundCondition){
		String refundDDesc = this.getRefundDesc(condition.getOrderNo(),condition.getSkuId());
		payRefundCondition.setOutTradeNo(condition.getOutTradeNo());
		payRefundCondition.setTotalAmount(condition.getTotalAmount());
		payRefundCondition.setRefundAmount(condition.getRefundAmount());
		payRefundCondition.setRefundDesc(condition.getRefundDesc());
		payRefundCondition.setCreatedBy(Long.parseLong(condition.getCreatedBy()));
		payRefundCondition.setCreatedByName(condition.getCreatedByName());
		payRefundCondition.setOrderNo(condition.getOrderNo());
		payRefundCondition.setOutRefundNo(condition.getRefundNo());
		payRefundCondition.setRefundDesc(refundDDesc);
	}

	/**
	 * 获取退款原因
	 * @return
	 */
	private String getRefundDesc(String orderNO, Long sku){
		OrderRefundDescCondition condition = new OrderRefundDescCondition();
		condition.setOrderNo(orderNO);
		condition.setSku(sku);
		return orderCancelInfoMapper.selectCancleReasonByCondition(condition);
	}

	/**
	 * 构造退款入参
	 * @param condition
	 */
	private void buildRefundCondition(OrderAfterSaleRefundCondition condition){
		BigDecimal orderMoney = this.getOrderMoney(condition.getOrderNo());
		BigDecimal refundMoney = this.getRefundMoney(condition);
		String orderTransactionNo = this.getOrderTransactionNo(condition.getOrderNo());
		String refundDesc = this.getRefundDesc(condition.getOrderNo(),condition.getSkuId());
		condition.setRefundNo(this.generateRefundNo(condition));
		condition.setOutTradeNo(orderTransactionNo);
		condition.setTotalAmount(orderMoney);
		condition.setRefundAmount(refundMoney);
		condition.setCreatedBy(condition.getCreatedBy());
		condition.setCreatedByName(condition.getCreatedByName());
		condition.setRefundDesc(refundDesc);
	}

	/**
	 * 生成退款单号
	 * @param condition
	 * @return
	 */
	private String generateRefundNo(OrderAfterSaleRefundCondition condition) {
		String refundNo = null;
		String randomFormat = "%05d";
		UUID uuid = UUID.randomUUID();
		int hashCodeV = (uuid.toString() + System.currentTimeMillis()).hashCode();
		if (hashCodeV < 0) {
			// 有可能是负数
			hashCodeV = -hashCodeV;
		}
		while (hashCodeV > MAX_ORDER_POSTFIX) {
			hashCodeV = hashCodeV >> 1;
		}
		String key="afterSaleRefund:no";
		if(org.apache.commons.lang3.StringUtils.isBlank(cache.get(key))){
			cache.setex(key,24*60*60,"0");
		}
		Long suff = cache.incrBy(key,1L);
		refundNo = "R" +condition.getType().intValue()+ condition.getOrderNo().replace("Y","") +String.format(randomFormat,hashCodeV)+ String.format(randomFormat, suff);
		return refundNo;
	}

	/**
	 * @return 获取退款金额
	 */
	private BigDecimal getRefundMoney(OrderAfterSaleRefundCondition condition){

		//获取订单信息
		OrderInfo orderInfo = orderInfoMapper.selectByOrderNo(condition.getOrderNo());
		//未发货仅退款
		if(AfterSaleRefundTypeEnum.WAIT_DELIVERING_REFUND.getTypeCode().intValue()==condition.getType().intValue()){
			return orderInfo.getOtherTotal();
		}else {
			OrderDetailRefundCondition con = new OrderDetailRefundCondition();
			con.setOrderNo(condition.getOrderNo());
			con.setSkuId(condition.getSkuId());
			OrderDetail orderDetail = orderDetailMapper.selectDetailByRefundCondition(con);
			return orderDetail.getOtherTotal().multiply(new BigDecimal(orderDetail.getNumber()));
		}
	}

	/**
	 * 获取订单金额
	 * @param orderNo
	 * @return
	 */
	private BigDecimal getOrderMoney(String orderNo){
		//获取订单信息
		OrderInfo orderInfo = orderInfoMapper.selectByOrderNo(orderNo);
		return orderInfo.getOtherTotal();
	}

	/**
	 * 获取支付流水号
	 * @param orderNo
	 * @return
	 */
	private String getOrderTransactionNo(String orderNo){
		OrderPayment orderPayPayment = orderPaymentMapper.selectByOrderNo(orderNo);
		return orderPayPayment.getOrderTransactionNo();
	}

	/**
	 * 保存日志
	 * @return
	 */
	private Integer saveOrderLog(OrderLog orderLog){
		return orderLogMapper.insertSelective(orderLog);
	}

}
